﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml.Serialization;

namespace myMap
{
    class Network
    {
        public List<Intersection> interList = new List<Intersection>();
        public List<RoadSection> roadList = new List<RoadSection>();

        
        /// <summary>
        /// 根据行向量和列向量创建网络 
        /// </summary>
        /// <param name="ROW">行向量</param>
        /// <param name="COLUMN">列向量</param>
        public void Create(int ROW, int COLUMN)
        {
            // 创建Intersections.
            CreateIntersections(ROW, COLUMN);

            // 创建RoadSections.
            CreateRoadSections();



            Console.WriteLine();
        }

        /// <summary>
        /// 创建RoadSections.
        /// 1 首先创建outgoing roads 并加入roads
        /// 2 然后创建incoming roads 并加入roads
        /// </summary>
        private void CreateRoadSections()
        {
            // 遍历所有intersections.

            // 在intersection的上下左右分别找有可能的
            // 道路，暂时不考虑环形的地图.

            // int nInters = this.interList.Count;
            foreach (Intersection eachInter in this.interList)
            {
                // 垂直方向
                // 尝试找出是否存在的intersection.
                // 如果存在，则建立道路
                Intersection findVerInter = FindVerticalInter(eachInter);
                if (null != findVerInter)
                {
                    CreateBidRoad(eachInter, findVerInter);
                }

                // 水平方向.
                // 尝试找出是否存在的intersection.
                // 如果存在，则建立道路
                Intersection findHorInter = FindHorzontalInter(eachInter);
                if (null != findHorInter)
                {
                    CreateBidRoad(eachInter, findHorInter);
                }

            }
           
        }

        /// <summary>
        /// 水平方向 从左边找Inter
        /// </summary>
        /// <param name="eachInter"></param>
        /// <returns></returns>
        private Intersection FindHorzontalInter(Intersection eachInter)
        {
            int nFindX = eachInter.X;
            int nFindY = eachInter.Y - 1;

            Intersection iRtn = FindInter(nFindX, nFindY);

            return iRtn;
        }

        /// <summary>
        /// 通过两个inter 建立双向Road
        /// </summary>
        /// <param name="eachInter">第一个inter</param>
        /// <param name="findInter">第二个inter</param>
        private void CreateBidRoad(Intersection eachInter, Intersection findInter)
        {
            RoadSection First = CreateOneWayRoad(eachInter, findInter);
            this.roadList.Add(First);

            RoadSection Second = CreateOneWayRoad(findInter, eachInter);
            this.roadList.Add(Second);
        }

        /// <summary>
        /// 创建一条道路
        /// 由第一个点指向第二个点.
        /// </summary>
        /// <param name="eachInter">第一个点</param>
        /// <param name="findInter">第二个点</param>
        /// <returns></returns>
        private RoadSection CreateOneWayRoad(Intersection startInter, 
                                                Intersection endInter)
        {
            //

            RoadSection road = new RoadSection();

            Intersection NewstartInter = road.GetStartInter();
            Intersection NewendInter = road.GetEndInter();

            NewstartInter = startInter;
            NewendInter = endInter;

            String strRoadName = String.Format("{0}_{1}",
                                                NewstartInter.ID,
                                                NewendInter.ID);

            road.Name = strRoadName;


            // 设置了开始点和结束点之后.
            // 这条道路针对开始点来说 是outgoings
            // 这条道路针对结束点来说 是incomings


            List<RoadSection> outgoings = startInter.GetOutgoings();
            List<RoadSection> incomings = endInter.GetIncomings();

            outgoings.Add(road);
            incomings.Add(road);


            return road;

        }

        /// <summary>
        /// 找向上的Intersection
        /// </summary>
        /// <param name="eachInter">当前参考inter.</param>
        /// <returns></returns>
        private Intersection FindVerticalInter(Intersection eachInter)
        {
            // 向上找的话 i - 1

            int nFindX = eachInter.X - 1;
            int nFindY = eachInter.Y;

            Intersection iRtn = FindInter(nFindX, nFindY);

            return iRtn;
        }

        /// <summary>
        /// 通过X和Y找到具体的Intersection
        /// </summary>
        /// <param name="nFindX">X 坐标</param>
        /// <param name="nFindY">Y 坐标</param>
        /// <returns></returns>
        private Intersection FindInter(int nFindX, int nFindY)
        {

            Intersection interRtn = null;

            foreach (Intersection eachInter in this.interList)
            {
                if ((nFindX == eachInter.X) && 
                   (nFindY == eachInter.Y))
                {
                    interRtn = eachInter;
                }
            }

            return interRtn;
        }

        /// <summary>
        /// 首先创建Intersection
        /// </summary>
        /// <param name="ROW">行向量</param>
        /// <param name="COLUMN">列向量</param>
        private void CreateIntersections(int ROW, int COLUMN)
        {
            for (int i = 0; i < ROW; i++)
            {
                for (int j = 0; j < COLUMN; j++)
                {
                    Intersection eachInter = new Intersection();
                    eachInter.X = i;
                    eachInter.Y = j;

                    // Create Name.
                    String strName = String.Format("{0},{1}",
                                                    eachInter.X,
                                                    eachInter.Y
                                                    );
                    // Set Name.
                    eachInter.ID = strName;

                    // Add to network.
                    this.interList.Add(eachInter);
                }
            }
        }

        public void WriteInter(string path)
        {
            FileStream stream = new FileStream(path,
                                    FileMode.Create);

            XmlSerializer serializer = new XmlSerializer(typeof(List<Intersection>));

            serializer.Serialize(stream, interList);
            stream.Close();
        }

        public void WriteRoads(string path)
        {
            FileStream stream = new FileStream(path,
                        FileMode.Create);

            XmlSerializer serializer = new XmlSerializer(typeof(List<RoadSection>));

            serializer.Serialize(stream, roadList);
            stream.Close();
        }

        /// <summary>
        /// 从文件读取数据.
        /// </summary>
        /// <param name="path"></param>
        public void ReadInter(string path)
        {
            FileStream stream = new FileStream(path, FileMode.Open);

            XmlSerializer serializer = new XmlSerializer(typeof(List<Intersection>));

            this.interList = (List<Intersection>)serializer.Deserialize(stream);

            stream.Close();
        }

        public void ReadRoads(string path)
        {
            FileStream stream = new FileStream(path, FileMode.Open);

            XmlSerializer serializer = new XmlSerializer(typeof(List<RoadSection>));

            this.roadList = (List<RoadSection>)serializer.Deserialize(stream);

            stream.Close();
        }


        /// <summary>
        /// 对inter的road建立联系
        /// </summary>
        public void Connect()
        {
            // 遍历所有道路.
            foreach (RoadSection eachRoad in this.roadList)
            {
                // 拆分名字
                String[] inters = eachRoad.Name.Split('_');

                // 根据名字找到对象并设置道路上引用
                Intersection interStart = GetInter(inters[0], this.interList);
                Intersection interEnd = GetInter(inters[1], this.interList);

                eachRoad.SetStart(interStart);
                eachRoad.SetEnd(interEnd);
    

                // 对开始点设置outgoing
                interStart.AddOutgoing(eachRoad);

                // 对结束点设置incoming
                interEnd.AddIncoming(eachRoad);
            }
        }

        /// <summary>
        /// 根据名字，返回对象.
        /// </summary>
        /// <param name="p"></param>
        /// <param name="list"></param>
        /// <returns></returns>
        private Intersection GetInter(string InterName, List<Intersection> list)
        {
            Intersection interRtn = null;

            foreach (Intersection eachInter in list)
            {
                if (InterName == eachInter.ID)
                {
                    interRtn = eachInter;
                    break;
                }
            }

            return interRtn;
        }
    }
}
